/**
 * 广寒宫
 * 网址:www.guanghangong.xyz
 */
package org.moon.framework.autoconfigure.datasource.routing;

import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.moon.framework.autoconfigure.config.SpringContextConfig;
import org.moon.framework.autoconfigure.mybatisplus.props.JdbcPoolProperties;
import org.moon.framework.autoconfigure.mybatisplus.props.JdbcProperties;

import java.util.Map;
import java.util.Optional;

/**
 * 数据源切换处理
 * @author moon
 */
@Slf4j
public class DynamicDataSourceContextHolder {

    /**
     * 使用ThreadLocal维护变量，ThreadLocal为每个使用该变量的线程提供独立的变量副本，
     *  所以每一个线程都可以独立地改变自己的副本，而不会影响其它线程所对应的副本。
     */
    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    /**
     * 设置数据源的变量
     */
    public static void setDataSourceType(String dsType, Map<Object, Object> dataSourcesMap) {
        log.info("切换到{}数据源", dsType);
        CONTEXT_HOLDER.set(dsType);
        DynamicDataSource dynamicDataSource = (DynamicDataSource) SpringContextConfig.getBean("dataSource");
        dynamicDataSource.setTargetDataSources(dataSourcesMap);
        dynamicDataSource.afterPropertiesSet();
    }

    /**
     * 获得数据源的变量
     */
    public static String getDataSourceType() {
        return CONTEXT_HOLDER.get();
    }

    /**
     * 清空数据源变量
     */
    public static void clearDataSourceType() {
        CONTEXT_HOLDER.remove();
    }

    /**
     * 构建数据源
     * @param jdbcProperties
     * @return
     */
    public static HikariDataSource buildDataSource(JdbcProperties jdbcProperties){
        JdbcPoolProperties poolProperties = jdbcProperties.getJdbcPool();
        HikariDataSource hikariDataSource = new HikariDataSource();
        hikariDataSource.setUsername(jdbcProperties.getUsername());
        hikariDataSource.setPassword(jdbcProperties.getPassword());
        hikariDataSource.setJdbcUrl(jdbcProperties.getUrl());
        Optional.ofNullable(poolProperties.getDriverClassName()).ifPresent(hikariDataSource::setDriverClassName);
        hikariDataSource.setAutoCommit(poolProperties.isAutoCommit());
        hikariDataSource.setConnectionTimeout(poolProperties.getConnectionTimeout());
        hikariDataSource.setIdleTimeout(poolProperties.getIdleTimeout());
        hikariDataSource.setMaxLifetime(poolProperties.getMaxLifetime());
        hikariDataSource.setMaximumPoolSize(poolProperties.getMaximumPoolSize());
        hikariDataSource.setMinimumIdle(poolProperties.getMinimumIdle());
        hikariDataSource.setInitializationFailTimeout(poolProperties.getInitializationFailTimeout());
        hikariDataSource.setIsolateInternalQueries(poolProperties.isIsolateInternalQueries());
        hikariDataSource.setReadOnly(poolProperties.isReadOnly());
        hikariDataSource.setRegisterMbeans(poolProperties.isRegisterMbeans());
        hikariDataSource.setValidationTimeout(poolProperties.getValidationTimeout());
        hikariDataSource.setLeakDetectionThreshold(poolProperties.getLeakDetectionThreshold());
        return hikariDataSource;
    }
}